<?php
declare(strict_types=1);

namespace App\Utils\Other\IdCardAuth;

use App\Exception\InternalException;
use App\Exception\InvalidRequestException;
use App\Utils\Http\Request;
use Hyperf\Collection\Arr;
use Hyperf\Di\Annotation\Inject;
use Psr\SimpleCache\CacheInterface;
use function Hyperf\Config\config;
use function Hyperf\Translation\__;

/**
 * 身份信息核实类
 * @author zx
 * @package other\chuanglan
 */
Class Chuanglan {

    /**
     * @var CacheInterface
     */
    #[Inject]
    protected CacheInterface $cache;

    /**
     * 请求路径
     * @var string
     */
    protected $url = '';

    /**
     * APPID
     * @var string
     */
    protected $appId = '';

    /**
     * APPKEY
     * @var string
     */
    protected $appKey = '';

    /**
     * 请求参数
     * @var array
     */
    private $param;

    public function __construct(
        protected Request $request
    )
    {
        $this->setConfig();
    }

    /**
     * 设置配置
     * @param array $config
     * @return $this
     */
    public function setConfig($config=[])
    {
        if (!$config) {
            $config = config('cloud.chuanglan.id_card_auth');
            $this->appId = Arr::get($config, 'app_id');
            $this->appKey = Arr::get($config, 'app_key');
            $this->url = Arr::get($config, 'url');
        } else {
            $this->appId = $config['app_id'];
            $this->appKey = $config['app_key'];
            $this->url = $config['url'];
        }
        return $this;
    }

    /**
     * 设置参数
     * @param $param
     * @param false $fail 是否直接抛出异常
     * @author zx
     * @return $this
     */
    public function set(string $idNum, string $name)
    {
        $keyName = 'id_card_auth_'.getInfo('mini', 'openid').'_'.date('Ymd');
        $num = $this->cache->get($keyName);
        if ($num >= 6) {
            throw new InvalidRequestException(__('message.payer.auth.count', ['num'=>6]));
        }
        $this->cache->set($keyName, $num+1, 86400);

        $param['idNum'] = $idNum;
        $param['name'] = $name;
        $param['sign'] = $this->sign($param);
        $param['appId'] = $this->appId;
        $this->param = $param;
        return $this;
    }

    /**
     * 获取结果
     * @return mixed
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function get()
    {
        $data = $this->request->formPost($this->url, $this->param);
        $result = json_decode($data, true);
        if ($result['code'] != 200000) {
            throw new InternalException("Code:[{$result['code']}] Message:[{$result['message']}]");
        }
        if ($result['data']['result'] !== '01') {
            throw new InternalException($result['data']['remark']);
        }
        return $result['data'];
    }

    /**
     * 获取签名
     * @param $param
     * @return string
     * @throws InvalidRequestException
     */
    protected function sign($param)
    {
        if ( !$this->appId || !$this->appKey ) {
            throw new InvalidRequestException(__('message.config.failed'));
        }
        $str = "appId{$this->appId}idNum{$param['idNum']}name{$param['name']}";
        $hex = hash_hmac("sha1", $str, $this->appKey, true);
        return base64_encode($hex);
    }

}